﻿using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.Runtime.CompilerServices;

public class ColorWheel : IDisposable
{
    private int brightness;
    private int brightnessMax;
    private int brightnessMin;
    private Point brightnessPoint;
    private Rectangle brightnessRectangle;
    private Region brightnessRegion;
    private double brightnessScaling;
    private int brightnessX;
    private Point centerPoint;
    private const int COLOR_COUNT = 0x600;
    public ColorChangedEventHandler ColorChanged;
    private Bitmap colorImage;
    private Point colorPoint;
    private Rectangle colorRectangle;
    private Region colorRegion;
    private MouseState currentState;
    private const double DEGREES_PER_RADIAN = 57.295779513082323;
    private System.Drawing.Color fullColor;
    private Graphics g;
    private ColorHandler.HSV HSV;
    private int radius;
    private ColorHandler.RGB RGB;
    private System.Drawing.Color selectedColor = System.Drawing.Color.White;
    private Rectangle selectedColorRectangle;

    public ColorWheel(Rectangle colorRectangle, Rectangle brightnessRectangle, Rectangle selectedColorRectangle)
    {
        using (GraphicsPath path = new GraphicsPath())
        {
            this.colorRectangle = colorRectangle;
            this.brightnessRectangle = brightnessRectangle;
            this.selectedColorRectangle = selectedColorRectangle;
            this.radius = Math.Min(colorRectangle.Width, colorRectangle.Height) / 2;
            this.centerPoint = colorRectangle.Location;
            this.centerPoint.Offset(this.radius, this.radius);
            this.colorPoint = this.centerPoint;
            path.AddEllipse(colorRectangle);
            this.colorRegion = new Region(path);
            this.brightnessMin = this.brightnessRectangle.Top;
            this.brightnessMax = this.brightnessRectangle.Bottom;
            path.AddRectangle(new Rectangle(brightnessRectangle.Left, brightnessRectangle.Top - 10, brightnessRectangle.Width + 10, brightnessRectangle.Height + 20));
            this.brightnessRegion = new Region(path);
            this.brightnessX = brightnessRectangle.Left + brightnessRectangle.Width;
            this.brightnessScaling = 255.0 / ((double) (this.brightnessMax - this.brightnessMin));
            this.brightnessPoint = new Point(this.brightnessX, this.brightnessMax);
            this.CreateGradient();
        }
    }

    private Point CalcBrightnessPoint(int brightness)
    {
        return new Point(this.brightnessX, this.brightnessMax - ((int) (((double) brightness) / this.brightnessScaling)));
    }

    private void CalcCoordsAndUpdate(ColorHandler.HSV HSV)
    {
        this.colorPoint = this.GetPoint((((double) HSV.Hue) / 255.0) * 360.0, (((double) HSV.Saturation) / 255.0) * this.radius, this.centerPoint);
        this.brightnessPoint = this.CalcBrightnessPoint(HSV.value);
        this.brightness = HSV.value;
        this.selectedColor = ColorHandler.HSVtoColor(HSV);
        this.RGB = ColorHandler.HSVtoRGB(HSV);
        this.fullColor = ColorHandler.HSVtoColor(HSV.Hue, HSV.Saturation, 0xff);
    }

    private int CalcDegrees(Point pt)
    {
        if (pt.X == 0)
        {
            if (pt.Y > 0)
            {
                return 270;
            }
            return 90;
        }
        int num = (int) (-Math.Atan(((double) pt.Y) / ((double) pt.X)) * 57.295779513082323);
        if (pt.X < 0)
        {
            num += 180;
        }
        return ((num + 360) % 360);
    }

    private void CreateGradient()
    {
        using (PathGradientBrush brush = new PathGradientBrush(this.GetPoints((double) this.radius, new Point(this.radius, this.radius))))
        {
            brush.CenterColor = System.Drawing.Color.White;
            brush.CenterPoint = new PointF((float) this.radius, (float) this.radius);
            brush.SurroundColors = this.GetColors();
            this.colorImage = new Bitmap(this.colorRectangle.Width, this.colorRectangle.Height, PixelFormat.Format32bppArgb);
            using (Graphics graphics = Graphics.FromImage(this.colorImage))
            {
                graphics.FillEllipse(brush, 0, 0, this.colorRectangle.Width, this.colorRectangle.Height);
            }
        }
    }

    public void Draw(Graphics g, ColorHandler.HSV HSV)
    {
        this.g = g;
        this.HSV = HSV;
        this.CalcCoordsAndUpdate(this.HSV);
        this.UpdateDisplay();
    }

    public void Draw(Graphics g, ColorHandler.RGB RGB)
    {
        this.g = g;
        this.HSV = ColorHandler.RGBtoHSV(RGB);
        this.CalcCoordsAndUpdate(this.HSV);
        this.UpdateDisplay();
    }

    public void Draw(Graphics g, Point mousePoint)
    {
        Point point4;
        Point colorPoint = this.colorPoint;
        Point brightnessPoint = this.brightnessPoint;
        this.g = g;
        if ((this.currentState == MouseState.MouseUp) && !mousePoint.IsEmpty)
        {
            if (this.colorRegion.IsVisible(mousePoint))
            {
                this.currentState = MouseState.ClickOnColor;
            }
            else if (this.brightnessRegion.IsVisible(mousePoint))
            {
                this.currentState = MouseState.ClickOnBrightness;
            }
            else
            {
                this.currentState = MouseState.ClickOutsideRegion;
            }
        }
        switch (this.currentState)
        {
            case MouseState.ClickOnColor:
            case MouseState.DragInColor:
            {
                colorPoint = mousePoint;
                Point pt = new Point(mousePoint.X - this.centerPoint.X, mousePoint.Y - this.centerPoint.Y);
                int num2 = this.CalcDegrees(pt);
                double num = Math.Sqrt((double) ((pt.X * pt.X) + (pt.Y * pt.Y))) / ((double) this.radius);
                if ((this.currentState == MouseState.DragInColor) && (num > 1.0))
                {
                    num = 1.0;
                    colorPoint = this.GetPoint((double) num2, (double) this.radius, this.centerPoint);
                }
                this.HSV.Hue = (num2 * 0xff) / 360;
                this.HSV.Saturation = (int) (num * 255.0);
                this.HSV.value = this.brightness;
                this.RGB = ColorHandler.HSVtoRGB(this.HSV);
                this.fullColor = ColorHandler.HSVtoColor(this.HSV.Hue, this.HSV.Saturation, 0xff);
                goto Label_0228;
            }
            case MouseState.ClickOnBrightness:
            case MouseState.DragInBrightness:
                point4 = mousePoint;
                if (point4.Y >= this.brightnessMin)
                {
                    if (point4.Y > this.brightnessMax)
                    {
                        point4.Y = this.brightnessMax;
                    }
                    break;
                }
                point4.Y = this.brightnessMin;
                break;

            default:
                goto Label_0228;
        }
        brightnessPoint = new Point(this.brightnessX, point4.Y);
        this.brightness = (int) ((this.brightnessMax - point4.Y) * this.brightnessScaling);
        this.HSV.value = this.brightness;
        this.RGB = ColorHandler.HSVtoRGB(this.HSV);
    Label_0228:
        this.selectedColor = ColorHandler.HSVtoColor(this.HSV);
        this.OnColorChanged(this.RGB, this.HSV);
        switch (this.currentState)
        {
            case MouseState.ClickOnColor:
                this.currentState = MouseState.DragInColor;
                break;

            case MouseState.ClickOnBrightness:
                this.currentState = MouseState.DragInBrightness;
                break;

            case MouseState.ClickOutsideRegion:
                this.currentState = MouseState.DragOutsideRegion;
                break;
        }
        this.colorPoint = colorPoint;
        this.brightnessPoint = brightnessPoint;
        this.UpdateDisplay();
    }

    private void DrawBrightnessPointer(Point pt)
    {
        Point[] points = new Point[] { pt, new Point(pt.X + 7, pt.Y + 5), new Point(pt.X + 7, pt.Y - 5) };
        this.g.FillPolygon(Brushes.Black, points);
    }

    private void DrawColorPointer(Point pt)
    {
        this.g.DrawRectangle(Pens.Black, pt.X - 3, pt.Y - 3, 6, 6);
    }

    private void DrawLinearGradient(System.Drawing.Color TopColor)
    {
        using (LinearGradientBrush brush = new LinearGradientBrush(this.brightnessRectangle, TopColor, System.Drawing.Color.Black, LinearGradientMode.Vertical))
        {
            this.g.FillRectangle(brush, this.brightnessRectangle);
        }
    }

    private System.Drawing.Color[] GetColors()
    {
        System.Drawing.Color[] colorArray = new System.Drawing.Color[0x600];
        for (int i = 0; i <= 0x5ff; i++)
        {
            colorArray[i] = ColorHandler.HSVtoColor((int) (((double) (i * 0xff)) / 1536.0), 0xff, 0xff);
        }
        return colorArray;
    }

    private Point GetPoint(double degrees, double radius, Point centerPoint)
    {
        double d = degrees / 57.295779513082323;
        return new Point(centerPoint.X + ((int) Math.Floor((double) (radius * Math.Cos(d)))), centerPoint.Y - ((int) Math.Floor((double) (radius * Math.Sin(d)))));
    }

    private Point[] GetPoints(double radius, Point centerPoint)
    {
        Point[] pointArray = new Point[0x600];
        for (int i = 0; i <= 0x5ff; i++)
        {
            pointArray[i] = this.GetPoint(((double) (i * 360)) / 1536.0, radius, centerPoint);
        }
        return pointArray;
    }

    protected void OnColorChanged(ColorHandler.RGB RGB, ColorHandler.HSV HSV)
    {
        ColorChangedEventArgs e = new ColorChangedEventArgs(RGB, HSV);
        this.ColorChanged(this, e);
    }

    public void SetMouseUp()
    {
        this.currentState = MouseState.MouseUp;
    }

    void IDisposable.Dispose()
    {
        if (this.colorImage != null)
        {
            this.colorImage.Dispose();
        }
        if (this.colorRegion != null)
        {
            this.colorRegion.Dispose();
        }
        if (this.brightnessRegion != null)
        {
            this.brightnessRegion.Dispose();
        }
        if (this.g != null)
        {
            this.g.Dispose();
        }
    }

    private void UpdateDisplay()
    {
        using (Brush brush = new SolidBrush(this.selectedColor))
        {
            this.g.DrawImage(this.colorImage, this.colorRectangle);
            this.g.FillRectangle(brush, this.selectedColorRectangle);
            this.DrawLinearGradient(this.fullColor);
            this.DrawColorPointer(this.colorPoint);
            this.DrawBrightnessPointer(this.brightnessPoint);
        }
    }

    public System.Drawing.Color Color
    {
        get
        {
            return this.selectedColor;
        }
    }

    public delegate void ColorChangedEventHandler(object sender, ColorChangedEventArgs e);

    public enum MouseState
    {
        MouseUp,
        ClickOnColor,
        DragInColor,
        ClickOnBrightness,
        DragInBrightness,
        ClickOutsideRegion,
        DragOutsideRegion
    }
}

